package student.aistar.day15.lock;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 循环打印abc ABC 123 abc ABC 123
 *
 * 打印小写字母abc得线程, 打印大写字母ABC线程, 打印数字123得线程
 *
 * 使用Lock中得同步队列 - 解决方案 - **唤醒指定的等待队列上的某个线程.**
 */
public class LockTongxinDemo {
    private Lock lock = new ReentrantLock();

    //有几个线程, 就构建几个队列

    //打印小写字母得
    private Condition c1 = lock.newCondition();
    private Condition c2 = lock.newCondition();
    private Condition c3 = lock.newCondition();

    //定义了一个标记
    private int count = 0;

    //count = 0 打印小写字母的执行
    //count = 1 打印大写字母的执行
    //count = 2 打印数字的执行

    //1. void await(); //当前线程会进入到阻塞状态, 必须要等其他线程唤醒得
    //2, void signal(); //哪个线程得Conition对象去调用signal()方法, 哪个线程就会被唤醒
    public void printLower(){
        while (true) {
            lock.lock();
            if (count == 0) {
                System.out.println("abc");
                count = 1;
                c2.signal();
            } else {
                count = 1;
                try {
                    c1.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            lock.unlock();
        }
    }

    public void printUpper(){
        while(true) {
            lock.lock();
            if (count == 1) {
                System.out.println("ABC");
                count = 2;
                c3.signal();
            } else {
                try {
                    c2.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            lock.unlock();
        }
    }

    public void printNumber(){
        while (true) {
            lock.lock();
            if (count == 2) {
                count = 0;
                System.out.println(123);
                c1.signal();
            } else {
                try {
                    c3.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        LockTongxinDemo demo = new LockTongxinDemo();
        Thread t1 = new Thread(()->{
            demo.printLower();
        });

        Thread t2 = new Thread(()->{
            demo.printUpper();
        });

        Thread t3 = new Thread(()->{
            demo.printNumber();
        });

        t1.start();
        t2.start();
        t3.start();
    }
}
